﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraEditors.Registrator;
using DevExpress.XtraEditors.ViewInfo;
using DevExpress.XtraEditors.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.ComponentModel;

namespace BuildHelper.Work.CommitHistory
{
    public class ByteArrayPopupControl : XtraUserControl
    {
        private DevExpress.XtraTab.XtraTabControl tabControl;
        private DevExpress.XtraTab.XtraTabPage tabText;
        private MemoEdit edMemo;
        private DevExpress.XtraTab.XtraTabPage tabRTF;
        private DevExpress.XtraRichEdit.RichEditControl edRtf;
        private PictureEdit edImage;
        private DevExpress.XtraTab.XtraTabPage tabImg;

        private void InitializeComponent()
        {
            this.tabControl = new DevExpress.XtraTab.XtraTabControl();
            this.tabText = new DevExpress.XtraTab.XtraTabPage();
            this.edMemo = new DevExpress.XtraEditors.MemoEdit();
            this.tabImg = new DevExpress.XtraTab.XtraTabPage();
            this.tabRTF = new DevExpress.XtraTab.XtraTabPage();
            this.edRtf = new DevExpress.XtraRichEdit.RichEditControl();
            this.edImage = new DevExpress.XtraEditors.PictureEdit();
            ((System.ComponentModel.ISupportInitialize)(this.tabControl)).BeginInit();
            this.tabControl.SuspendLayout();
            this.tabText.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.edMemo.Properties)).BeginInit();
            this.tabImg.SuspendLayout();
            this.tabRTF.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.edImage.Properties)).BeginInit();
            this.SuspendLayout();
            // 
            // tabControl
            // 
            this.tabControl.Dock = System.Windows.Forms.DockStyle.Fill;
            this.tabControl.Location = new System.Drawing.Point(0, 0);
            this.tabControl.Name = "tabControl";
            this.tabControl.SelectedTabPage = this.tabText;
            this.tabControl.ShowTabHeader = DevExpress.Utils.DefaultBoolean.True;
            this.tabControl.Size = new System.Drawing.Size(418, 224);
            this.tabControl.TabIndex = 0;
            this.tabControl.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] {
            this.tabText,
            this.tabImg,
            this.tabRTF});
            // 
            // tabText
            // 
            this.tabText.Controls.Add(this.edMemo);
            this.tabText.Name = "tabText";
            this.tabText.Size = new System.Drawing.Size(411, 195);
            this.tabText.Text = "Text";
            // 
            // edMemo
            // 
            this.edMemo.Dock = System.Windows.Forms.DockStyle.Fill;
            this.edMemo.Location = new System.Drawing.Point(0, 0);
            this.edMemo.Name = "edMemo";
            this.edMemo.Size = new System.Drawing.Size(411, 195);
            this.edMemo.TabIndex = 0;
            // 
            // tabImg
            // 
            this.tabImg.Controls.Add(this.edImage);
            this.tabImg.Name = "tabImg";
            this.tabImg.Size = new System.Drawing.Size(411, 195);
            this.tabImg.Text = "Image";
            // 
            // tabRTF
            // 
            this.tabRTF.Controls.Add(this.edRtf);
            this.tabRTF.Name = "tabRTF";
            this.tabRTF.Size = new System.Drawing.Size(411, 195);
            this.tabRTF.Text = "RTF";
            // 
            // edRtf
            // 
            this.edRtf.ActiveViewType = DevExpress.XtraRichEdit.RichEditViewType.Simple;
            this.edRtf.Dock = System.Windows.Forms.DockStyle.Fill;
            this.edRtf.Location = new System.Drawing.Point(0, 0);
            this.edRtf.Name = "edRtf";
            this.edRtf.Size = new System.Drawing.Size(411, 195);
            this.edRtf.TabIndex = 0;
            this.edRtf.Text = "richEditControl1";
            // 
            // edImage
            // 
            this.edImage.Dock = System.Windows.Forms.DockStyle.Fill;
            this.edImage.Location = new System.Drawing.Point(0, 0);
            this.edImage.Name = "edImage";
            this.edImage.Size = new System.Drawing.Size(411, 195);
            this.edImage.TabIndex = 0;
            // 
            // ByteArrayPopupControl
            // 
            this.Controls.Add(this.tabControl);
            this.Name = "ByteArrayPopupControl";
            this.Size = new System.Drawing.Size(418, 224);
            ((System.ComponentModel.ISupportInitialize)(this.tabControl)).EndInit();
            this.tabControl.ResumeLayout(false);
            this.tabText.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.edMemo.Properties)).EndInit();
            this.tabImg.ResumeLayout(false);
            this.tabRTF.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.edImage.Properties)).EndInit();
            this.ResumeLayout(false);

        }

        public string GetPlainText(byte[] bytes)
        {
            edRtf.RtfText = bytes.ByteArrayToString();
            return edRtf.Text;
        }

        internal void SetRepository(RepositoryItemByteArrayEdit repositoryItemByteArrayEdit)
        {
            
        }
    }

    public class ByteArrayEdit : DevExpress.XtraEditors.PopupContainerEdit
    {
        [Category("Properties")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Description("Gets an object containing properties, methods and events specific to the editors.")]
        public new RepositoryItemByteArrayEdit Properties
        {
            get { return fProperties as RepositoryItemByteArrayEdit; }
        }

        protected override void CreateRepositoryItem()
        {
            this.fProperties = new RepositoryItemByteArrayEdit(this);
        }

        
    }

    public class RepositoryItemByteArrayEdit : DevExpress.XtraEditors.Repository.RepositoryItemPopupContainerEdit
    {
        public const string ByteArrayName = "ByteArrayEdit";
        static RepositoryItemByteArrayEdit() {
            Register();
        }
        public static void Register()
        {
            EditorRegistrationInfo.Default.Editors.Add(new EditorClassInfo(ByteArrayName, typeof(ByteArrayEdit),
                typeof(RepositoryItemByteArrayEdit), typeof(PopupContainerEditViewInfo),
                new ButtonEditPainter(), true, null, typeof(DevExpress.Accessibility.PopupEditAccessible)));
        }

        public RepositoryItemByteArrayEdit()
        {
            Initialize();
        }
        protected override void RaiseQueryPopUp(CancelEventArgs e)
        {
            base.RaiseQueryPopUp(e);
            if (PopupControl != null && byteArrayControl != null)
            {
                byteArrayControl.SetRepository(this);
            }
        }
        public RepositoryItemByteArrayEdit(ByteArrayEdit byteArrayEdit)
        {
            Initialize();
            SetOwnerEdit(byteArrayEdit);
        }

        private void Initialize()
        {
            ImageWord = "Image";
            TextWord = "Text";
            RtfWord = "RTF";
        }
        public ByteArrayType DataType
        {
            get;
            set;
        }

        public string ImageWord { get; set; }
        public string TextWord { get; set; }
        public string RtfWord { get; set; }
        private PopupContainerControl customPopupControl;
        private ByteArrayPopupControl byteArrayControl;

        public override PopupContainerControl PopupControl
        {
            get
            {
                if (customPopupControl == null)
                {
                    customPopupControl = new PopupContainerControl();
                    byteArrayControl = new ByteArrayPopupControl();
                    byteArrayControl.Dock = DockStyle.Fill;
                    customPopupControl.Controls.Add(byteArrayControl);
                }
                return customPopupControl;
            }
            set
            {

                customPopupControl = value;
            }
        }
        
        public override string GetDisplayText(DevExpress.Utils.FormatInfo format, object editValue)
        {
            string s = string.Empty;
            if (editValue.IsNotNull())
            {
                if (editValue is byte[])
                {
                    ByteArrayType t = DataType;
                    if (t == ByteArrayType.Auto)
                    {
                        string mime = getMimeFromByteArray(editValue as byte[]);
                        if (mime == "text/richtext")
                            t = ByteArrayType.Rtf;
                        if (mime.StartsWith("text"))
                            t = ByteArrayType.Text;
                        else if (mime.StartsWith("image"))
                            t = ByteArrayType.Image;
                    }
                    switch (t)
                    {
                        case ByteArrayType.Text:
                            s = (editValue as byte[]).ByteArrayToString();
                            break;
                        case ByteArrayType.Rtf:
                            if (byteArrayControl != null)
                            {
                                s = byteArrayControl.GetPlainText(editValue as byte[]);
                            }
                            else
                            {
                                using (RichTextBox rtb = new RichTextBox())
                                {
                                    rtb.Rtf = (editValue as byte[]).ByteArrayToString();
                                    s = rtb.Text;
                                }
                            }
                            break;
                        case ByteArrayType.Image:
                            s = ImageWord;
                            break;
                        default:
                            break;
                    }
                }
                else
                {
                    s = editValue.AsString();
                }
            }
            
            return s;
        }

        [DllImport(@"urlmon.dll", CharSet = CharSet.Auto)]
        private extern static System.UInt32 FindMimeFromData(
            System.UInt32 pBC,
            [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl,
            [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer,
            System.UInt32 cbSize,
            [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed,
            System.UInt32 dwMimeFlags,
            out System.UInt32 ppwzMimeOut,
            System.UInt32 dwReserverd
        );
        private static string getMimeFromByteArray(byte[] buffer)
        {
            try
            {
                System.UInt32 mimetype;
                FindMimeFromData(0, null, buffer, 256, null, 0, out mimetype, 0);
                System.IntPtr mimeTypePtr = new IntPtr(mimetype);
                string mime = Marshal.PtrToStringUni(mimeTypePtr);
                Marshal.FreeCoTaskMem(mimeTypePtr);
                return mime;
            }
            catch (Exception)
            {
                return "unknown/unknown";
            }
        }
    }


    public enum ByteArrayType
    {
        Auto,
        Text,
        Rtf,
        Image
    }
}
